#include "WidgetTower.hpp"


WidgetTower::WidgetTower(const char *pRootPath, const char *pIniUIFilename, const char *pIniDriverMappingFilename, const char *pIniVehiculeClassMappingFilename)
{
	initialized = false;
	rootPath = pRootPath; 
	iniDriverMappingFilename = pIniDriverMappingFilename;
	iniVehiculeClassMappingFilename = pIniVehiculeClassMappingFilename;

	nbProfiles = GetPrivateProfileInt("Profiles", "count", 0, pIniUIFilename);
	for (int i = 0 ; i < nbProfiles; i++) {
		sprintf(tmp, "Profile.%d", (i+1));
		profiles[i].widgetOffsetX = (signed int)GetPrivateProfileInt(tmp, "Tower.offsetX", 0, pIniUIFilename);
		profiles[i].widgetOffsetY = (signed int)GetPrivateProfileInt(tmp, "Tower.offsetY", 0, pIniUIFilename);
		profiles[i].hide = GetPrivateProfileInt(tmp, "Tower.hide", 0, pIniUIFilename) != 0;
	}

	//std::string str = rootPath;
	GetPrivateProfileString("UI Widgets", "Tower.ini", "", tmp, 999, pIniUIFilename);
	//str.append(tmp);
	sprintf(iniUIFilename, "%s%s", rootPath, tmp);
	//iniUIFilename = str.c_str(); //pIniUIFilename; 
	available = GetPrivateProfileInt("Tower", "available", 0, iniUIFilename) != 0;

	nbDrivers = 0;
	towerMode = 0;
}


WidgetTower::~WidgetTower(void)
{
}

void WidgetTower::init(const ScreenInfoV01 &info, float ratio, float ratioWidth, float ratioHeight, Sprite spriteList[]) {
	if (!available) {
		initialized = true;
		return;
	}

	for (int i = 0 ; i < nbProfiles; i++) {
		profiles[i].widgetOffsetX *= ratioWidth;
		profiles[i].widgetOffsetY *= ratioHeight;
	}

	int posX = (int)(ratioWidth * GetPrivateProfileInt("Tower", "image.left", 0, iniUIFilename));
	int posY = (int)(ratioHeight * GetPrivateProfileInt("Tower", "image.top", 0, iniUIFilename));

	//LPDIRECT3DDEVICE9 dev = static_cast<LPDIRECT3DDEVICE9>(info.mDevice);	
	

	bgImageData.spriteIndex = GetPrivateProfileInt("Tower", "image.id", 0, iniUIFilename) -1;
	if (bgImageData.spriteIndex > -1) {
		bgImageData.left = posX;
		bgImageData.top = posY;
		bgImageData.width = (int)(GetPrivateProfileInt("Tower", "image.width", (int)spriteList[bgImageData.spriteIndex].width, iniUIFilename) * ratioWidth);
		bgImageData.height = (int)(GetPrivateProfileInt("Tower", "image.height", (int)spriteList[bgImageData.spriteIndex].height, iniUIFilename) * ratioHeight);
		bgImageData.colorIndex = GetPrivateProfileInt("Tower", "image.color.id", 1, iniUIFilename) -1;
	}
	nextLineOffsetY = GetPrivateProfileInt("Tower", "new.line.offsetY", 16, iniUIFilename) * ratioHeight;
	maxNbDriverDisplayed = GetPrivateProfileInt("Tower", "driver.count", 10, iniUIFilename);

	// line bg
	lineBgAvailable = GetPrivateProfileInt("Tower.Line.Background", "available", 0, iniUIFilename) != 0;
	lineBgImageData.spriteIndex = GetPrivateProfileInt("Tower.Line.Background", "image.id", 0, iniUIFilename) -1;
	if (lineBgImageData.spriteIndex > -1) {
		lineBgImageData.left = (int)(posX + GetPrivateProfileInt("Tower.Line.Background", "image.left", 0, iniUIFilename) * ratioWidth);
		lineBgImageData.top = (int)(posY + GetPrivateProfileInt("Tower.Line.Background", "image.top", 0, iniUIFilename) * ratioHeight);
		lineBgImageData.width = (int)(GetPrivateProfileInt("Tower.Line.Background", "image.width", (int)spriteList[lineBgImageData.spriteIndex].width, iniUIFilename) * ratioWidth);
		lineBgImageData.height = (int)(GetPrivateProfileInt("Tower.Line.Background", "image.height", (int)spriteList[lineBgImageData.spriteIndex].height, iniUIFilename) * ratioHeight);
		lineBgImageData.colorIndex = GetPrivateProfileInt("Tower.Line.Background", "image.color.id", 1, iniUIFilename) -1;
	}
	// driver place
	placeAvailable = GetPrivateProfileInt("Tower.Place", "available", 0, iniUIFilename) != 0;
	if (placeAvailable) {
		//rctDriverPlace.left = spBackground->position.x + (202 + 2) * ratioWidth;
		//rctDriverPlace.top = spBackground->position.y + (18 + 4) * ratioHeight;
		//rctDriverPlace.right = spBackground->position.x + 236 * ratioWidth;
		//rctDriverPlace.bottom = spBackground->position.y + 57 * ratioHeight;
		placeTextData.fontIndex = GetPrivateProfileInt("Tower.Place", "text.font.id", 1, iniUIFilename) - 1;
		placeTextData.colorIndex = GetPrivateProfileInt("Tower.Place", "text.font.color.id", 1, iniUIFilename) - 1;
		placeTextData.rect.left = (int)(posX + GetPrivateProfileInt("Tower.Place", "text.left", 0, iniUIFilename) * ratioWidth);
		placeTextData.rect.top = (int)(posY + GetPrivateProfileInt("Tower.Place", "text.top", 0, iniUIFilename) * ratioHeight);
		placeTextData.rect.right = (int)(posX + GetPrivateProfileInt("Tower.Place", "text.right", 100, iniUIFilename) * ratioWidth);
		placeTextData.rect.bottom = (int)(posY + GetPrivateProfileInt("Tower.Place", "text.bottom", 100, iniUIFilename) * ratioHeight);
		placeTextData.alignment = GetPrivateProfileInt("Tower.Place", "text.alignment", 1, iniUIFilename);

		placeImageData.spriteIndex = GetPrivateProfileInt("Tower.Place", "image.id", 0, iniUIFilename) -1;
		if (placeImageData.spriteIndex != -1) {
			placeImageData.left = (int)(posX + GetPrivateProfileInt("Tower.Place", "image.left", 0, iniUIFilename) * ratioWidth);
			placeImageData.top = (int)(posY + GetPrivateProfileInt("Tower.Place", "image.top", 0, iniUIFilename) * ratioHeight);
			placeImageData.width = (int)(GetPrivateProfileInt("Tower.Place", "image.width", (int)spriteList[placeImageData.spriteIndex].width, iniUIFilename) * ratioWidth);
			placeImageData.height = (int)(GetPrivateProfileInt("Tower.Place", "image.height", (int)spriteList[placeImageData.spriteIndex].height, iniUIFilename) * ratioHeight);
			placeImageData.colorIndex = GetPrivateProfileInt("Tower.Place", "image.color.id", 1, iniUIFilename) -1;
		}

		firstPlaceAvailable =  GetPrivateProfileInt("Tower.FirstAllCat", "available", 0, iniUIFilename) != 0;
		if (firstPlaceAvailable) {
			firstPlaceTextData.rect.left = (int)(posX + GetPrivateProfileInt("Tower.FirstAllCat", "text.left", -9999, iniUIFilename) * ratioWidth);
			firstPlaceTextData.rect.top = (int)(posY + GetPrivateProfileInt("Tower.FirstAllCat", "text.top", -9999, iniUIFilename) * ratioHeight);
			firstPlaceTextData.rect.right = (int)(posX + GetPrivateProfileInt("Tower.FirstAllCat", "text.right", -9999, iniUIFilename) * ratioWidth);
			firstPlaceTextData.rect.bottom = (int)(posY + GetPrivateProfileInt("Tower.FirstAllCat", "text.bottom", -9999, iniUIFilename) * ratioHeight);
			if (firstPlaceTextData.rect.left < 0) firstPlaceTextData.rect.left = placeTextData.rect.left;
			if (firstPlaceTextData.rect.top < 0) firstPlaceTextData.rect.top = placeTextData.rect.top;
			if (firstPlaceTextData.rect.right < 0 ) firstPlaceTextData.rect.right = placeTextData.rect.right;
			if (firstPlaceTextData.rect.bottom < 0) firstPlaceTextData.rect.bottom = placeTextData.rect.bottom;

			firstPlaceTextData.fontIndex = GetPrivateProfileInt("Tower.FirstAllCat", "text.font.id", 1, iniUIFilename) - 1;
			firstPlaceTextData.colorIndex = GetPrivateProfileInt("Tower.FirstAllCat", "text.font.color.id", 1, iniUIFilename) - 1;
			firstPlaceTextData.alignment = GetPrivateProfileInt("Tower.FirstAllCat", "text.alignment", 1, iniUIFilename);

			firstPlaceImageData.spriteIndex = GetPrivateProfileInt("Tower.FirstAllCat", "image.id", 0, iniUIFilename) -1;
			if (firstPlaceImageData.spriteIndex != -1) {
				firstPlaceImageData.left = (int)(posX + GetPrivateProfileInt("Tower.FirstAllCat", "image.left", 0, iniUIFilename) * ratioWidth);
				firstPlaceImageData.top = (int)(posY + GetPrivateProfileInt("Tower.FirstAllCat", "image.top", 0, iniUIFilename) * ratioHeight);
				firstPlaceImageData.width = (int)(GetPrivateProfileInt("Tower.FirstAllCat", "image.width", (int)spriteList[firstPlaceImageData.spriteIndex].width, iniUIFilename) * ratioWidth);
				firstPlaceImageData.height = (int)(GetPrivateProfileInt("Tower.FirstAllCat", "image.height", (int)spriteList[firstPlaceImageData.spriteIndex].height, iniUIFilename) * ratioHeight);
				firstPlaceImageData.colorIndex = GetPrivateProfileInt("Tower.FirstAllCat", "image.color.id", 1, iniUIFilename) -1;
			}

		}

		firstPlaceInCatAvailable =  GetPrivateProfileInt("Tower.FirstInCat", "available", 0, iniUIFilename) != 0;
		if (firstPlaceInCatAvailable) {
			firstPlaceInCatTextData.rect.left = (int)(posX + GetPrivateProfileInt("Tower.FirstInCat", "text.left", -9999, iniUIFilename) * ratioWidth);
			firstPlaceInCatTextData.rect.top = (int)(posY + GetPrivateProfileInt("Tower.FirstInCat", "text.top", -9999, iniUIFilename) * ratioHeight);
			firstPlaceInCatTextData.rect.right = (int)(posX + GetPrivateProfileInt("Tower.FirstInCat", "text.right", -9999, iniUIFilename) * ratioWidth);
			firstPlaceInCatTextData.rect.bottom = (int)(posY + GetPrivateProfileInt("Tower.FirstInCat", "text.bottom", -9999, iniUIFilename) * ratioHeight);
			if (firstPlaceInCatTextData.rect.left < 0) firstPlaceInCatTextData.rect.left = placeTextData.rect.left;
			if (firstPlaceInCatTextData.rect.top < 0) firstPlaceInCatTextData.rect.top = placeTextData.rect.top;
			if (firstPlaceInCatTextData.rect.right < 0 ) firstPlaceInCatTextData.rect.right = placeTextData.rect.right;
			if (firstPlaceInCatTextData.rect.bottom < 0) firstPlaceInCatTextData.rect.bottom = placeTextData.rect.bottom;

			firstPlaceInCatTextData.fontIndex = GetPrivateProfileInt("Tower.FirstInCat", "text.font.id", 1, iniUIFilename) - 1;
			firstPlaceInCatTextData.colorIndex = GetPrivateProfileInt("Tower.FirstInCat", "text.font.color.id", 1, iniUIFilename) - 1;
			firstPlaceInCatTextData.alignment = GetPrivateProfileInt("Tower.FirstInCat", "text.alignment", 1, iniUIFilename);

			firstPlaceInCatImageData.spriteIndex = GetPrivateProfileInt("Tower.FirstInCat", "image.id", 0, iniUIFilename) -1;
			if (firstPlaceInCatImageData.spriteIndex != -1) {
				firstPlaceInCatImageData.left = (int)(posX + GetPrivateProfileInt("Tower.FirstInCat", "image.left", 0, iniUIFilename) * ratioWidth);
				firstPlaceInCatImageData.top = (int)(posY + GetPrivateProfileInt("Tower.FirstInCat", "image.top", 0, iniUIFilename) * ratioHeight);
				firstPlaceInCatImageData.width = (int)(GetPrivateProfileInt("Tower.FirstInCat", "image.width", (int)spriteList[firstPlaceInCatImageData.spriteIndex].width, iniUIFilename) * ratioWidth);
				firstPlaceInCatImageData.height = (int)(GetPrivateProfileInt("Tower.FirstInCat", "image.height", (int)spriteList[firstPlaceInCatImageData.spriteIndex].height, iniUIFilename) * ratioHeight);
				firstPlaceInCatImageData.colorIndex = GetPrivateProfileInt("Tower.FirstInCat", "image.color.id", 1, iniUIFilename) -1;
			}

		}
	} 

	// Driver name
	driverNameAvailable = GetPrivateProfileInt("Tower.DriverName", "available", 0, iniUIFilename) != 0;
	if (driverNameAvailable) {
		driverNameTextData.fontIndex = GetPrivateProfileInt("Tower.DriverName", "text.font.id", 1, iniUIFilename) - 1;
		driverNameTextData.colorIndex = GetPrivateProfileInt("Tower.DriverName", "text.font.color.id", 1, iniUIFilename) - 1;
		driverNameTextData.rect.left = (int)(posX + GetPrivateProfileInt("Tower.DriverName", "text.left", -9999, iniUIFilename) * ratioWidth);
		driverNameTextData.rect.top = (int)(posY + GetPrivateProfileInt("Tower.DriverName", "text.top", -9999, iniUIFilename) * ratioHeight);
		driverNameTextData.rect.right = (int)(posX + GetPrivateProfileInt("Tower.DriverName", "text.right", -9999, iniUIFilename) * ratioWidth);
		driverNameTextData.rect.bottom = (int)(posY + GetPrivateProfileInt("Tower.DriverName", "text.bottom", -9999, iniUIFilename) * ratioHeight);
		driverNameTextData.alignment = GetPrivateProfileInt("Tower.DriverName", "text.alignment", 1, iniUIFilename);

	}

	// category
	categoryAvailable =  GetPrivateProfileInt("Tower.Category", "available", 0, iniUIFilename) != 0;
	if (categoryAvailable) {
		categoryTextData.rect.left = (int)(posX + GetPrivateProfileInt("Tower.Category", "text.left", 0, iniUIFilename) * ratioWidth);
		categoryTextData.rect.top = (int)(posY + GetPrivateProfileInt("Tower.Category", "text.top", 0, iniUIFilename) * ratioWidth);
		categoryTextData.rect.right = (int)(posX + GetPrivateProfileInt("Tower.Category", "text.right", 100, iniUIFilename) * ratioWidth);
		categoryTextData.rect.bottom = (int)(posY + GetPrivateProfileInt("Tower.Category", "text.bottom", 100, iniUIFilename) * ratioWidth);

		categoryTextData.fontIndex = GetPrivateProfileInt("Tower.Category", "text.font.id", 1, iniUIFilename) - 1;
		categoryTextData.colorIndex = GetPrivateProfileInt("Tower.Category", "text.font.color.id", 1, iniUIFilename) - 1;
		categoryTextData.alignment = GetPrivateProfileInt("Tower.Category", "text.alignment", 1, iniUIFilename);

		categoryOriginalTextColorIndex = categoryTextData.colorIndex;

		categoryImageData.spriteIndex = GetPrivateProfileInt("Tower.Category", "image.id", 0, iniUIFilename) -1;
		if (categoryImageData.spriteIndex != -1) {
			categoryImageData.left = (int)(posX + GetPrivateProfileInt("Tower.Category", "image.left", 0, iniUIFilename) * ratioWidth);
			categoryImageData.top = (int)(posY + GetPrivateProfileInt("Tower.Category", "image.top", 0, iniUIFilename) * ratioHeight);
			categoryImageData.width = (int)(GetPrivateProfileInt("Tower.Category", "image.width", (int)spriteList[categoryImageData.spriteIndex].width, iniUIFilename) * ratioWidth);
			categoryImageData.height = (int)(GetPrivateProfileInt("Tower.Category", "image.height", (int)spriteList[categoryImageData.spriteIndex].height, iniUIFilename) * ratioHeight);
			categoryImageData.colorIndex = GetPrivateProfileInt("Tower.Category", "image.color.id", 1, iniUIFilename) -1;
			categoryOriginalImageColorIndex = categoryImageData.colorIndex;
		}
	}

	// Number
	numberAvailable = GetPrivateProfileInt("Tower.Number", "available", 0, iniUIFilename) != 0;
	if (numberAvailable) {
		numberTextData.fontIndex = GetPrivateProfileInt("Tower.Number", "text.font.id", 1, iniUIFilename) - 1;
		numberTextData.colorIndex = GetPrivateProfileInt("Tower.Number", "text.font.color.id", 1, iniUIFilename) - 1;
		numberTextData.rect.left = (int)(posX + GetPrivateProfileInt("Tower.Number", "text.left", -9999, iniUIFilename) * ratioWidth);
		numberTextData.rect.top = (int)(posY + GetPrivateProfileInt("Tower.Number", "text.top", -9999, iniUIFilename) * ratioHeight);
		numberTextData.rect.right = (int)(posX + GetPrivateProfileInt("Tower.Number", "text.right", -9999, iniUIFilename) * ratioWidth);
		numberTextData.rect.bottom = (int)(posY + GetPrivateProfileInt("Tower.Number", "text.bottom", -9999, iniUIFilename) * ratioHeight);
		numberTextData.alignment = GetPrivateProfileInt("Tower.Number", "text.alignment", 1, iniUIFilename);
	}

	// Data
	dataAvailable = GetPrivateProfileInt("Tower.Data", "available", 0, iniUIFilename) != 0;
	if (dataAvailable) {
		autoSizeGap = GetPrivateProfileInt("Tower.Data", "autosize.pixel.gap", 4, iniUIFilename);
		
		dataTextData.fontIndex = GetPrivateProfileInt("Tower.Data", "text.font.id", 1, iniUIFilename) - 1;
		dataTextData.colorIndex = GetPrivateProfileInt("Tower.Data", "text.font.color.id", 1, iniUIFilename) - 1;
		dataTextData.rect.left = (int)(posX + GetPrivateProfileInt("Tower.Data", "text.left", -9999, iniUIFilename) * ratioWidth);
		dataTextData.rect.top = (int)(posY + GetPrivateProfileInt("Tower.Data", "text.top", -9999, iniUIFilename) * ratioHeight);
		dataTextData.rect.right =  (int)(posX + GetPrivateProfileInt("Tower.Data", "text.right", -9999, iniUIFilename) * ratioWidth);
		dataTextData.rect.bottom = (int)(posY + GetPrivateProfileInt("Tower.Data", "text.bottom", -9999, iniUIFilename) * ratioHeight);
		dataTextData.alignment = GetPrivateProfileInt("Tower.Data", "text.alignment", 1, iniUIFilename);

		dataImageData.spriteIndex = GetPrivateProfileInt("Tower.Data", "image.id", 0, iniUIFilename) -1;
		if (dataImageData.spriteIndex != -1) {
			dataImageData.left = (int)(posX + GetPrivateProfileInt("Tower.Data", "image.left", 0, iniUIFilename) * ratioWidth);
			dataImageData.top = (int)(posY + GetPrivateProfileInt("Tower.Data", "image.top", 0, iniUIFilename) * ratioHeight);
			dataImageData.width = (int)(GetPrivateProfileInt("Tower.Data", "image.width", (int)spriteList[dataImageData.spriteIndex].width, iniUIFilename) * ratioWidth);
			dataImageData.height = (int)(GetPrivateProfileInt("Tower.Data", "image.height", (int)spriteList[dataImageData.spriteIndex].height, iniUIFilename) * ratioHeight);
			dataImageData.colorIndex = GetPrivateProfileInt("Tower.Data", "image.color.id", 1, iniUIFilename) -1;
		}
	}
}

	void WidgetTower::updateData(const ScoringInfoV01 &info, DriverInfo orderedDriverInfos[]) {
		if (!available ) return;

		nbDrivers = info.mNumVehicles;

	}


	void WidgetTower::render(int profileIndex, const ScreenInfoV01 &info, bool isRace, const LPD3DXFONT *fontList, const D3DCOLOR *colorList, Sprite spriteList[], DriverInfo orderedDriverInfos[], TimingInfoPerCategoryMap & timingInfoPerCategoryMap, int activeCategoryIndex) { 
		if (!available) return;
		if (gReplayIsActive) return;
		if (profiles[profileIndex].hide) return;

		int memWidgetOffsetY = profiles[profileIndex].widgetOffsetY;
		LPDIRECT3DDEVICE9 dev = static_cast<LPDIRECT3DDEVICE9>(info.mDevice);	
		if (bgImageData.spriteIndex > -1) {
			spriteList[bgImageData.spriteIndex].setPosition(bgImageData.left + profiles[profileIndex].widgetOffsetX, bgImageData.top + profiles[profileIndex].widgetOffsetY);
			spriteList[bgImageData.spriteIndex].setSize(bgImageData.width, bgImageData.height);
			spriteList[bgImageData.spriteIndex].render(dev, colorList[bgImageData.colorIndex], 100);
		}	

		std::string strKey;
		TimingInfo * catTiming;
		int relativePlaceDriver = 0;
		int currentCategoryIndex = 0;
		std::string activeCategory;
		double leaderTimingSecond = -1;
		short leaderLapCompleted = 0;
		double leaderLapDistance = 0;
		double timeBehindLeader = -1;
		for (int i = 0; i < maxNbDriverDisplayed; i++) {
			if (i >= nbDrivers) break;

			DriverInfo & di = orderedDriverInfos[i];	  
			strKey = "C_";
			strKey.append(di.mCategoryName);
			TimingInfoPerCategoryMap::iterator it = timingInfoPerCategoryMap.find(strKey);
			catTiming = &it->second;

			
			if (i == 0 || catTiming->bestPlaceID == di.mID) {
				if (currentCategoryIndex < activeCategoryIndex) {
					currentCategoryIndex++;
					if (activeCategoryIndex == currentCategoryIndex) {
						activeCategory = strKey.c_str();
						timeBehindLeader = -1;
					}
				}
			}

			if (activeCategoryIndex != 0) {
				if (activeCategoryIndex != currentCategoryIndex) {
					continue;
				} else if (activeCategory.compare(strKey) != 0) {
					timeBehindLeader += abs(di.timeBehindNextInFront);
					continue;
				}
			}
			if (timeBehindLeader < 0) {
				timeBehindLeader = 0;
			} else {
				timeBehindLeader += abs(di.timeBehindNextInFront);
			}
			relativePlaceDriver++;
			sprintf(tmp, "%d", relativePlaceDriver);

			// line bg
			if (lineBgAvailable) {
				if(lineBgImageData.spriteIndex != -1) {
					spriteList[lineBgImageData.spriteIndex].setPosition(lineBgImageData.left + profiles[profileIndex].widgetOffsetX, lineBgImageData.top + profiles[profileIndex].widgetOffsetY);
					spriteList[lineBgImageData.spriteIndex].setSize(lineBgImageData.width, lineBgImageData.height);
					spriteList[lineBgImageData.spriteIndex].render(dev, colorList[lineBgImageData.colorIndex], 100);
				}
			}

			// Place
			if (placeAvailable) {
				if ((i+1) == 1 && firstPlaceAvailable) {
					if (firstPlaceImageData.spriteIndex != -1) {
						spriteList[firstPlaceImageData.spriteIndex].setPosition(firstPlaceImageData.left + profiles[profileIndex].widgetOffsetX, firstPlaceImageData.top + profiles[profileIndex].widgetOffsetY);
						spriteList[firstPlaceImageData.spriteIndex].setSize(firstPlaceImageData.width, firstPlaceImageData.height);
						spriteList[firstPlaceImageData.spriteIndex].render(dev, colorList[firstPlaceImageData.colorIndex], 100);
					}
					tmpRect.left = firstPlaceTextData.rect.left + profiles[profileIndex].widgetOffsetX;
					tmpRect.top = firstPlaceTextData.rect.top + profiles[profileIndex].widgetOffsetY;
					tmpRect.right = firstPlaceTextData.rect.right + profiles[profileIndex].widgetOffsetX;
					tmpRect.bottom = firstPlaceTextData.rect.bottom + profiles[profileIndex].widgetOffsetY;
					fontList[firstPlaceTextData.fontIndex]->DrawTextA(NULL, tmp, -1, &tmpRect, firstPlaceTextData.alignment, colorList[firstPlaceTextData.colorIndex]);
				} else if (catTiming->bestPlaceID == di.mID && firstPlaceInCatAvailable) {
					if (firstPlaceInCatImageData.spriteIndex != -1) {
						spriteList[firstPlaceInCatImageData.spriteIndex].setPosition(firstPlaceInCatImageData.left + profiles[profileIndex].widgetOffsetX, firstPlaceInCatImageData.top + profiles[profileIndex].widgetOffsetY);
						spriteList[firstPlaceInCatImageData.spriteIndex].setSize(firstPlaceInCatImageData.width, firstPlaceInCatImageData.height);
						spriteList[firstPlaceInCatImageData.spriteIndex].render(dev, colorList[firstPlaceInCatImageData.colorIndex], 100);
					}
					tmpRect.left = firstPlaceInCatTextData.rect.left + profiles[profileIndex].widgetOffsetX;
					tmpRect.top = firstPlaceInCatTextData.rect.top + profiles[profileIndex].widgetOffsetY;
					tmpRect.right = firstPlaceInCatTextData.rect.right + profiles[profileIndex].widgetOffsetX;
					tmpRect.bottom = firstPlaceInCatTextData.rect.bottom + profiles[profileIndex].widgetOffsetY;
					fontList[firstPlaceInCatTextData.fontIndex]->DrawTextA(NULL, tmp, -1, &tmpRect, firstPlaceInCatTextData.alignment, colorList[firstPlaceInCatTextData.colorIndex]);
				} else {
					if (placeImageData.spriteIndex != -1) {
						spriteList[placeImageData.spriteIndex].setPosition(placeImageData.left + profiles[profileIndex].widgetOffsetX, placeImageData.top + profiles[profileIndex].widgetOffsetY);
						spriteList[placeImageData.spriteIndex].setSize(placeImageData.width, placeImageData.height);
						spriteList[placeImageData.spriteIndex].render(dev, colorList[placeImageData.colorIndex], 100);
					}
					tmpRect.left = placeTextData.rect.left + profiles[profileIndex].widgetOffsetX;
					tmpRect.top = placeTextData.rect.top + profiles[profileIndex].widgetOffsetY;
					tmpRect.right = placeTextData.rect.right + profiles[profileIndex].widgetOffsetX;
					tmpRect.bottom = placeTextData.rect.bottom + profiles[profileIndex].widgetOffsetY;
					fontList[placeTextData.fontIndex]->DrawTextA(NULL, tmp, -1, &tmpRect, placeTextData.alignment, colorList[placeTextData.colorIndex]);
				}
			}
			// Driver name
			if (driverNameAvailable) {
				tmpRect.left = driverNameTextData.rect.left + profiles[profileIndex].widgetOffsetX;
				tmpRect.top = driverNameTextData.rect.top + profiles[profileIndex].widgetOffsetY;
				tmpRect.right = driverNameTextData.rect.right + profiles[profileIndex].widgetOffsetX;
				tmpRect.bottom = driverNameTextData.rect.bottom + profiles[profileIndex].widgetOffsetY;

				fontList[driverNameTextData.fontIndex]->DrawTextA(NULL, orderedDriverInfos[i].mDriverName, -1, &tmpRect, driverNameTextData.alignment, colorList[driverNameTextData.colorIndex]);
			}

			// Category
			if (categoryAvailable) {
				if (di.mCategoryTextColorIndex == -1) {
					categoryTextData.colorIndex = categoryOriginalTextColorIndex;
				} else {
					categoryTextData.colorIndex = di.mCategoryTextColorIndex;
				}
				if (di.mCategoryImageColorIndex == -1) {
					categoryImageData.colorIndex = categoryOriginalImageColorIndex;
				} else {
					categoryImageData.colorIndex = di.mCategoryImageColorIndex;
				}
				if (categoryAvailable) {
					if( categoryImageData.spriteIndex != -1) {
						spriteList[categoryImageData.spriteIndex].setPosition(categoryImageData.left + profiles[profileIndex].widgetOffsetX, categoryImageData.top + profiles[profileIndex].widgetOffsetY);
						spriteList[categoryImageData.spriteIndex].setSize(categoryImageData.width, categoryImageData.height);
						spriteList[categoryImageData.spriteIndex].render(dev, colorList[categoryImageData.colorIndex], 100);
					}
					tmpRect.left = categoryTextData.rect.left + profiles[profileIndex].widgetOffsetX;
					tmpRect.top = categoryTextData.rect.top + profiles[profileIndex].widgetOffsetY;
					tmpRect.right = categoryTextData.rect.right + profiles[profileIndex].widgetOffsetX;
					tmpRect.bottom = categoryTextData.rect.bottom + profiles[profileIndex].widgetOffsetY;
					fontList[categoryTextData.fontIndex]->DrawTextA(NULL, di.mCategoryName, -1, &tmpRect, categoryTextData.alignment, colorList[categoryTextData.colorIndex]);
				}
			}

			// Number
			if (numberAvailable) {
				tmpRect.left = numberTextData.rect.left + profiles[profileIndex].widgetOffsetX;
				tmpRect.top = numberTextData.rect.top + profiles[profileIndex].widgetOffsetY;
				tmpRect.right = numberTextData.rect.right + profiles[profileIndex].widgetOffsetX;
				tmpRect.bottom = numberTextData.rect.bottom + profiles[profileIndex].widgetOffsetY;
				fontList[numberTextData.fontIndex]->DrawTextA(NULL, di.mDriverNumStr, -1, &tmpRect, numberTextData.alignment, colorList[numberTextData.colorIndex]);
			}

			// Data
			if (dataAvailable && towerMode > 0) {
				if (towerMode == 1) {
					if (isRace) {
						if (di.finishStatus == 1) {
							sprintf(tmp,"FINISH");
						} else if (di.finishStatus == 2) {
							sprintf(tmp,"DNF");
						} else if (di.finishStatus == 3) {
							sprintf(tmp,"DQ");
						} else if (di.isInPit) {
							sprintf(tmp,"PIT");
						} else {
							if (leaderTimingSecond == -1) {
								sprintf(tmp, "Lap %d", di.lapCompleted);
								leaderTimingSecond = 0; // just used to do not enter here again
								leaderLapCompleted = di.lapCompleted;
								leaderLapDistance = di.lapDistance;
							} else {
								int laps = leaderLapCompleted - di.lapCompleted;
								if (di.lapDistance > leaderLapDistance) {
									laps --;
								}
								if (laps >= 2) { // laps behind
									sprintf(tmp, "+%d Laps", laps);
								} else if (laps == 1) { // laps behind
									sprintf(tmp, "+%d Lap", laps);
								} else {
									sprintf(tmp, "+%s", getTimeAsString(timeBehindLeader, false, false, true, true).c_str());
								}
							}
						}
					} else {
						if (di.mBestLapTime > 0) {
							if (leaderTimingSecond == -1) {
								sprintf(tmp, "%s", getTimeAsString(di.mBestLapTime, false, false, true, true).c_str());
								leaderTimingSecond = di.mBestLapTime;
							} else {
								sprintf(tmp, "+%s", getTimeAsString(di.mBestLapTime - leaderTimingSecond, false, false, true, true).c_str());
							}
						} else {
							sprintf(tmp,"--:--.---");
						}
					}
				} else if (towerMode == 2) {
					if (di.mNumPitstops > 1) {
						sprintf(tmp,"%d Pits", di.mNumPitstops);
					} else {
						sprintf(tmp,"%d Pit", di.mNumPitstops);
					}
				} else if (towerMode == 3) {
					if (di.lapCompleted > 1) {
						sprintf(tmp,"%d Laps", di.lapCompleted);
					} else {
						sprintf(tmp,"%d Laps", di.lapCompleted);
					}
				}
				tmpRect.left = dataTextData.rect.left + profiles[profileIndex].widgetOffsetX;
				tmpRect.top = dataTextData.rect.top + profiles[profileIndex].widgetOffsetY;
				tmpRect.right = dataTextData.rect.right + profiles[profileIndex].widgetOffsetX;
				tmpRect.bottom = dataTextData.rect.bottom + profiles[profileIndex].widgetOffsetY;
				if (dataImageData.spriteIndex != -1) {
					spriteList[dataImageData.spriteIndex].setPosition(dataImageData.left + profiles[profileIndex].widgetOffsetX, dataImageData.top + profiles[profileIndex].widgetOffsetY);
					spriteList[dataImageData.spriteIndex].setSize(dataImageData.width, dataImageData.height);
					spriteList[dataImageData.spriteIndex].render(dev, colorList[dataImageData.colorIndex], 100);
				}
				fontList[dataTextData.fontIndex]->DrawTextA(NULL, tmp, -1, &tmpRect, dataTextData.alignment, colorList[dataTextData.colorIndex]);
			}

			profiles[profileIndex].widgetOffsetY += nextLineOffsetY;
		} 
		
		profiles[profileIndex].widgetOffsetY = memWidgetOffsetY;

	}

	std::string WidgetTower::getTimeAsString(double seconds, bool forceAllFields, bool padHighest, bool showMillis, bool showFullMillis) {
		if ( showMillis )
            seconds = floor(0.5 + seconds * 1000 ) / 1000;
        else
            seconds = floor(0.5 + seconds );
        
		std:string str = "";

		if ( seconds < 0 )
        {
			str.append("-");
            seconds *= -1;
        }
        
        int hours = (int)( seconds / 3600 );
        
        if ( ( hours > 0 ) || forceAllFields )
        {
            if ( padHighest ) {
				if (hours < 10) {
					str.append("0");
				}
			}
			str.append(std::to_string(static_cast<long long>(hours)));
			str.append(":");
        }
        
        int minutes = ((int) ( seconds / 60 )) % 60 ;
        
        if ( ( hours > 0 ) || ( minutes > 0 ) || forceAllFields )
        {
            if ( ( hours > 0 ) || padHighest ) {
				if (minutes < 10) {
					str.append("0");
				}
			}
			str.append(std::to_string(static_cast<long long>(minutes)));
			str.append(":");
        }
        
        int restSeconds = showMillis ? ((int)floor(seconds)) % 60 : ((int)(floor(0.5 + seconds))) % 60 ;
        
        if ( ( hours > 0 ) || ( minutes > 0 ) || padHighest ) {
            if (restSeconds < 10) {
					str.append("0");
			}
		}
		str.append(std::to_string(static_cast<long long>(restSeconds)));
        
        if ( showMillis )
        {
            int millis = showFullMillis ? ( (int)floor( 0.5 + seconds * 1000 )) % 1000  : ((int) floor( 0.5 + seconds * 10 )) % 10 ;
			str.append(".");
            
            if ( showFullMillis ) {
				if (millis < 10) {
					str.append("00");
				} else if (millis < 100) {
					str.append("0");
				}
			}
			str.append(std::to_string(static_cast<long long>(millis)));
        }
		return str;
	}